#include <chrono>
#include <thread>
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"

using namespace std::chrono_literals;
using namespace std::placeholders; // NOLINT

class ServiceClient_01 : public rclcpp::Node
{
public:
    ServiceClient_01(std::string name) : Node(name)
    {
        RCLCPP_INFO(this->get_logger(), "I am service client 01: %s", name.c_str());
        client_ = this->create_client<example_interfaces::srv::AddTwoInts>("add_tow_ints_srv");
    }

    void handle()
    {
        std::thread{std::bind(&ServiceClient_01::sendRequest, this)}.detach();
    }

    void sendRequest()
    {
        // 1,等待server上线
        while (!client_->wait_for_service(1s))
        {
            // failed,检查rclcpp状态
            if (!rclcpp::ok())
            {
                RCLCPP_INFO(this->get_logger(), "interrupted while waiting for service.");
                return;
            }
            RCLCPP_INFO(this->get_logger(), "Wainting for the server to work...");
        }
        // 2,构造请求
        int n1 = 0, n2 = 0;
        std::cin >> n1 >> n2;
        auto request = std::make_shared<example_interfaces::srv::AddTwoInts_Request>();
        request->a = n1;
        request->b = n2;
        // 3,发送请求
        using responseFuture = rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedFuture;
        auto response_received_callback = [this](responseFuture result_future)
        {
            auto response = result_future.get();
            RCLCPP_INFO(this->get_logger(), "Caculate result: %ld", response->sum);
            // std::cout << "Client spin thread id==" << std::this_thread::get_id() << std::endl;
        };
        // client_->async_send_request(request, std::bind(&ServiceClient_01::_responseCallback, this, std::placeholders::_1));
        auto client_result = client_->async_send_request(request, response_received_callback);
        RCLCPP_INFO(this->get_logger(), "send request and return immediately...");
        RCLCPP_INFO(this->get_logger(), "开始阻塞...");
        int value = client_result.get()->sum; // 阻塞，等待异步线程收到并设置响应
        RCLCPP_INFO(this->get_logger(), "成功获取响应数据，解除阻塞.");
        RCLCPP_INFO(this->get_logger(), "The sum is: %d", value);
    }

private:
    rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client_{};

    // 回调函数
    void _responseCallback(rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedFuture result_future)
    {
        auto response = result_future.get();
        RCLCPP_INFO(this->get_logger(), "Caculate result: %ld", response->sum);
        std::cout << "Client spin thread id==" << std::this_thread::get_id() << std::endl;
    }
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    std::cout << "Client main thread id==" << std::this_thread::get_id() << std::endl;
    auto node = std::make_shared<ServiceClient_01>("service_client_01");
    node->sendRequest();
    // node->handle();
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}